package com.danjinwulian.web.controller.mp;

import com.alibaba.fastjson2.JSONObject;
import com.danjinwulian.common.constant.Constants;
import com.danjinwulian.common.constant.IoTConstants;
import com.danjinwulian.common.core.controller.BaseController;
import com.danjinwulian.common.core.domain.AjaxResult;
import com.danjinwulian.common.core.domain.entity.IotDevice;
import com.danjinwulian.common.core.domain.entity.IotHotel;
import com.danjinwulian.common.core.domain.entity.IotTenant;
import com.danjinwulian.common.enums.RequestMethodEnum;
import com.danjinwulian.common.utils.DateUtils;
import com.danjinwulian.common.utils.StringUtils;
import com.danjinwulian.common.utils.WxUtils;
import com.danjinwulian.common.utils.uuid.IdUtils;
import com.danjinwulian.device.service.*;
import com.danjinwulian.framework.web.service.TokenService;
import com.danjinwulian.web.controller.common.CommonController;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestController
public class WeixinController extends BaseController
{
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);

    @Autowired
    private IMpWeixinService weixinService;

    @Autowired
    private IIotHotelService hotelService;

    @Autowired
    private IIotTenantService tenantService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IIotDeviceService deviceService;

    @Value("${weixin.danjinwulian.name}")
    private String danjinIotName;
    @Value("${weixin.danjinwulian.appid}")
    private String danjinIotAppId;
    @Value("${weixin.danjinwulian.secret}")
    private String danjinIotSecret;

    @Value("${weixin.hotel.appid}")
    private String hotelAppId;
    @Value("${weixin.hotel.secret}")
    private String hotelSecret;

    @Value("${weixin.tenant.appid}")
    private String tenantAppId;
    @Value("${weixin.tenant.secret}")
    private String tenantSecret;

    @Value("${weixin.message.getPowerSuccessTemplateId}")
    private String getPowerSuccessTemplateId;
    @Value("${weixin.message.deviceExceptionTemplateId}")
    private String deviceExceptionTemplateId;

    /**
     *开发者提交信息后，微信服务器将发送GET请求到填写的服务器地址URL上.
     * 开发者通过检验signature对请求进行校验（下面有校验方式）。
     * 若确认此次GET请求来自微信服务器，请原样返回echostr参数内容，
     * 则接入生效，成为开发者成功，否则接入失败。加密/校验流程如下：
     *
     * 1）将token、timestamp、nonce三个参数进行字典序排序
     * 2）将三个参数字符串拼接成一个字符串进行sha1加密
     * 3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
     * signature 微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
     * timestamp 时间戳
     * nonce 随机数
     * echostr 随机字符串
     * @return echostr 随机字符串
     */
    @RequestMapping(value = "/weixin/accept", method = {RequestMethod.POST, RequestMethod.GET})
    public void getAccept(HttpServletRequest request, HttpServletResponse response){
        System.out.println("接收微信信息...");
        try {
            String method = request.getMethod();
            if(RequestMethodEnum.GET.getDesc().equals(method)){
                String signature = request.getParameter("signature");
                String timestamp = request.getParameter("timestamp");
                String nonce = request.getParameter("nonce");
                String echoStr = request.getParameter("echostr");
                String token = "danjinwulian";
                boolean checkSignature = WxUtils.checkSignature(signature, timestamp, nonce, token);
                if (checkSignature) {
                    response.getWriter().write(echoStr+"");
                }
            } else {
                response.setHeader("Content-type", "application/xml");

                // 读取参数，解析Xml为map
                Map<String, String> map = WxUtils.xmlToMap(request);
                System.out.println("微信接收到的消息为:"+map.toString());
                JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(map));
                if(ObjectUtils.isNotEmpty(jsonObject)){
                    String fromUserName = jsonObject.getString("FromUserName");//消息来源用户标识
                    String toUserName = jsonObject.getString("ToUserName");//消息目的用户标识
                    String msgType = jsonObject.getString("MsgType");//消息类型(event或者text)
                    String eventType = jsonObject.getString("Event");//事件类型
                    String createTime = jsonObject.getString("CreateTime");

                    System.out.println("消息来源于:"+fromUserName);
                    System.out.println("openId:"+toUserName);
                    System.out.println("消息类型为:"+msgType);
                    System.out.println("事件类型为:"+eventType);

                    if (WxUtils.MSGTYPE_EVENT.equals(msgType)) {
                        String eventKey = jsonObject.getString("EventKey");
                        String deviceName = "";
                        System.out.println("事件类型值为:"+eventKey);
                        if(WxUtils.MESSAGE_SUBSCIBE.equals(eventType)) {//处理关注事件
                            if (StringUtils.isNotEmpty(eventKey) && eventKey.startsWith("qrscene_DeviceName:")) {
                                deviceName = eventKey.substring(eventKey.indexOf(":")+1);
                            }

                            String content = "你好，欢迎关注" + danjinIotName + "！请点击上面信息的WiFi密码，并按提示自动连接本房间WiFi免费用电，保持WiFi连接才不会断电哦。";
                            response.setCharacterEncoding("UTF-8");
                            response.getWriter().write(WxUtils.getXmlReturnMsg(fromUserName, toUserName, System.currentTimeMillis() / 1000, content));
                        } else if(WxUtils.MESSAGE_SCAN.equals(eventType)) {//处理扫码事件
                            if (eventKey.startsWith("DeviceName:")) {   //扫描取电二维码事件
                                deviceName = eventKey.substring(eventKey.indexOf(":")+1);
                            }
                        }

                        //发送公众号模板消息
                        if (StringUtils.isNotEmpty(deviceName)) {
                            IotDevice iotDevice = deviceService.selectDeviceByDeviceName(deviceName);
                            if (StringUtils.isNotNull(iotDevice)) {
                                IotHotel hotel = hotelService.selectIotHotelByHotelId(iotDevice.getHotelId());
                                // 获取accessToken
                                String accessToken = weixinService.getAccessToken("danjinwulian", danjinIotAppId, danjinIotSecret);
                                System.out.println("danjinIotAppId:"+danjinIotAppId+", danjinIotSecret:"+danjinIotSecret);
                                System.out.println("accessToken:"+accessToken);
                                if (StringUtils.isNotEmpty(accessToken)) {
                                    Map<String, Object> params = new HashMap<>();
                                    params.put("touser", fromUserName);

                                    //如果设备未上线，发送设备异常提醒
                                    if (!IoTConstants.DEVICE_ONLINE.equals(iotDevice.getStatus())) {
                                        params.put("template_id", deviceExceptionTemplateId);

                                        Map paramsData = new HashMap();
                                        paramsData.put("thing6", WxUtils.createParamsData(deviceName, null));
                                        paramsData.put("thing12", WxUtils.createParamsData("设备处于离线状态或未激活。", null));
                                        paramsData.put("phrase13", WxUtils.createParamsData("设备异常", null));
                                        paramsData.put("time15", WxUtils.createParamsData(DateUtils.getTime(), null));
                                        params.put("data", paramsData);
                                    } else {
                                        //如果设备已启用扫码开电，发送扫码开电通知
                                        if (IoTConstants.DEVICE_SPO_ENABLE.equals(iotDevice.getScanPoweron())) {
                                            params.put("template_id", getPowerSuccessTemplateId);

                                            Map paramsMp = new HashMap();
                                            paramsMp.put("appid", tenantAppId);
                                            paramsMp.put("pagepath", "pages/scan-power/scan-power?wifiName="+iotDevice.getWifiName()+"&wifiPswd="+iotDevice.getWifiPswd()+"&productId="+iotDevice.getProductId()+"&deviceName="+iotDevice.getDeviceName()+"&userName="+hotel.getHotelName()+"&roomName="+iotDevice.getRoomName());
                                            params.put("miniprogram", paramsMp);

                                            Map paramsData = new HashMap();
//                                        paramsData.put("first", WxUtils.createParamsData("尊敬的住客您好，欢迎入住" + hotel.getHotelName() + iotDevice.getRoomName() + "房间，温馨提示：请连接本房间WiFi，以确保本房间持续供电。", null));
//                                        paramsData.put("first", WxUtils.createParamsData("尊敬的住客您好，欢迎入住" + iotDevice.getRoomName() + "房间，温馨提示：请连接本房间WiFi，以确保本房间持续供电。", null));
//                                        paramsData.put("keyword1", WxUtils.createParamsData(DateUtils.getTime(), null));
//                                        paramsData.put("keyword2", WxUtils.createParamsData(iotDevice.getWifiName(), null));
//                                        paramsData.put("keyword3", WxUtils.createParamsData(iotDevice.getWifiPswd(), null));
//                                        paramsData.put("remark", WxUtils.createParamsData("点我一键连WiFi，不连会断电哦", "#ff4d00"));

                                            paramsData.put("thing2", WxUtils.createParamsData("【" + iotDevice.getRoomName() + "】", null));
                                            paramsData.put("time1", WxUtils.createParamsData(DateUtils.getTime(), null));
                                            paramsData.put("thing3", WxUtils.createParamsData(iotDevice.getWifiName(), null));
                                            paramsData.put("character_string4", WxUtils.createParamsData(iotDevice.getWifiPswd(), null));
                                            paramsData.put("thing5", WxUtils.createParamsData("点我一键连WiFi，不连会断电哦", null));
                                            params.put("data", paramsData);
                                        } else {
                                            params.put("template_id", deviceExceptionTemplateId);

                                            Map paramsData = new HashMap();
//                                        paramsData.put("first", WxUtils.createParamsData("房间已被禁用扫码开电功能，请联系酒店管理者开启扫码开电功能。", null));
//                                        paramsData.put("keyword1", WxUtils.createParamsData(DateUtils.getTime(), null));
//                                        paramsData.put("keyword2", WxUtils.createParamsData(hotel.getHotelName()+iotDevice.getRoomName(), null));
//                                        paramsData.put("remark", WxUtils.createParamsData("房间WiFi："+iotDevice.getWifiName()+" "+iotDevice.getWifiPswd(), null));

                                            paramsData.put("thing6", WxUtils.createParamsData(deviceName, null));
                                            paramsData.put("thing12", WxUtils.createParamsData("房间已被禁用扫码开电功能。", null));
                                            paramsData.put("phrase13", WxUtils.createParamsData("扫码异常", null));
                                            paramsData.put("time15", WxUtils.createParamsData(DateUtils.getTime(), null));
                                            params.put("data", paramsData);
                                        }
                                    }

                                    weixinService.pushTemplateMessage(accessToken, params);
                                }

                                //保存关注用户信息
                                IotTenant tenant = tenantService.selectIotTenantByGzhopenid(fromUserName);
                                if (StringUtils.isNull(tenant)) {
                                    tenant = new IotTenant();
                                    tenant.setDeviceId(iotDevice.getDeviceId());
                                    tenant.setGzhopenid(fromUserName);
                                    tenantService.insertIotTenant(tenant);
                                }
                            }
                        }
                    } else {//收到消息自动回复
//                        content = "/:sun已经收到您的消息~";
                    }
                }
            }
        } catch (IOException | DocumentException e) {
            throw new RuntimeException(e);
        }
    }

    @PostMapping("/weixin/hotelLogin")
    public AjaxResult wxLogin(@RequestBody IotHotel hotel)
    {
        // 参数校验
        if (StringUtils.isEmpty(hotel.getPhoneNumberCode())) {
            return AjaxResult.error("参数code为空，请重试！");
        }
        // 获取accessToken
        String accessToken = weixinService.getAccessToken("hotel", hotelAppId, hotelSecret);
        if (StringUtils.isEmpty(accessToken)) {
            return AjaxResult.error("获取accessToken失败，请重试！");
        }
        // 获取用户手机号
        String phoneNumber = weixinService.getUserPhoneNumber(accessToken, hotel.getPhoneNumberCode());
        if (StringUtils.isEmpty(phoneNumber)) {
            return AjaxResult.error("获取用户手机号失败，请重试！");
        }

        AjaxResult ajax = AjaxResult.success();

        IotHotel existHotel = hotelService.selectIotHotelByHotelPhone(phoneNumber);
        if (StringUtils.isNotNull(existHotel) && IoTConstants.NORMAL.equals(existHotel.getStatus())) {
            // 生成令牌
            ajax.put(Constants.TOKEN, IdUtils.fastUUID());
            ajax.put("hotel_id", existHotel.getHotelId());
        } else {
            ajax.put("msg", "用户不存在");
        }

        return ajax;
    }

    @PostMapping("/weixin/tenantLogin")
    public AjaxResult wxTenantLogin(@RequestBody IotTenant tenant)
    {
        // 参数校验
        if (StringUtils.isEmpty(tenant.getLoginCode())) {
            return AjaxResult.error("参数code为空，请重试！");
        }
        // 获取accessToken
        String accessToken = weixinService.getAccessToken("tenant", tenantAppId, tenantSecret);
        if (StringUtils.isEmpty(accessToken)) {
            return AjaxResult.error("获取accessToken失败，请重试！");
        }

        AjaxResult ajax = AjaxResult.success();



        return ajax;
    }

    @GetMapping("/weixin/getWxSign")
    public AjaxResult getWxSign(String url) {
        AjaxResult ajax = AjaxResult.success();

        String jsapiTicket = WxUtils.getJsapiTicket(weixinService.getAccessToken("danjinwulian", danjinIotAppId, danjinIotSecret));
        // 生成随机字符串
        String nonceStr = WxUtils.createNonceStr();
        // 时间戳
        long timestamp = System.currentTimeMillis();
        // 通过jsapi_ticket、随机字符串、时间戳
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("jsapi_ticket=").append(jsapiTicket).append("&")
                .append("noncestr=").append(nonceStr).append("&")
                .append("timestamp=").append(timestamp).append("&")
                .append("url=").append(url.indexOf("#") >= 0 ? url.substring(0, url.indexOf("#")) : url);
        String signatureStr = stringBuilder.toString();
        log.info("微信签名 she1加密前的数据：{}", signatureStr);
        String signature = DigestUtils.sha1Hex(signatureStr);
        log.info("微信签名，she1加密后的数据：{}", signature);

        ajax.put("url", url);
        ajax.put("appId", danjinIotAppId);
        ajax.put("nonceStr", nonceStr);
        ajax.put("timestamp", timestamp);
        ajax.put("signature", signature);

        return ajax;
    }
}
